package com.cloneoner.video
{
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;


	/**
	 * @author Thibault Loup - Cloneoner.com
	 */
	public class Cl360Slice extends Sprite
	{
		
		
		
		// __________________________________________________________
		// -										 	  CONSTRUCTOR
		
		/**
		 * Constructor
		 *  
		 * @param pSlices The slices 
		 * @param pHitZone The zone for mouseDown, mouseUp, rollOver & rollOut
		 */
		public function Cl360Slice(pSlices:Vector.<BitmapData>, pHitZone:Rectangle=null)
		{
			_slice = new ClAbstractSlicePlayer(pSlices);
			_rect = pHitZone ? pHitZone : new Rectangle(0, 0, _slice.width, _slice.height);
			_build();
		}
		
		// __________________________________________________________
		// -										  PUBLICS METHODS
		
		/** Start */
		public function start():void
		{
			_lastFrame = 
			_indice = _slice.currentFrame;
			addEventListener(Event.ENTER_FRAME, _onEnterFrame);
		}
		
		/** Stop */
		public function stop():void
		{
			removeEventListener(Event.ENTER_FRAME, _onEnterFrame);
		}
		
		/** Dispose */
		public function dispose():void
		{
			while (numChildren) removeChildAt(0);
			
			_onRemoved(null);
			
			removeEventListener(Event.ENTER_FRAME, _onEnterFrame);
			removeEventListener(Event.REMOVED_FROM_STAGE, _onRemoved);
			
			if( _hitZone)
				_hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
				
			if( _slice)
				_slice.dispose();
				
			_slice = null;
			_hitZone = null;
		}
		
		// __________________________________________________________
		// -										 		   EVENTS
		
		/** @private */
		private function _onRemoved(e:Event):void
		{
			if( stage)
				stage.removeEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
		}
		
		/** @private */
		private function _onMouseDown(e:MouseEvent):void
		{
			_lastFrame = _slice.currentFrame;
			_xFrame = _getXFrame();
			_isDragging = true;
			
			stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
		}
		
		/** @private */
		private function _onMouseUp(e:MouseEvent):void
		{
			_isDragging = true;
			stage.removeEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
		}
		
		/** @private */
		private function _onEnterFrame(e:Event):void
		{
			if ( _isDragging)
				_f = _getXFrame();
				
			if( !_f ) return;
			
			var f : Number = _lastFrame + _f - _xFrame;
			var i:Number = _indice;
			i += ( int(f) - i ) * _VELOCITY;
			var oi : Number = i;
			i = _checkLimit(i);
			if ( oi != i ) _lastFrame += i - oi;
			_slice.currentFrame = i;
			_indice = i;
		}
		
		// __________________________________________________________
		// -										 PRIVATES METHODS
		
		/** @private */
		private function _build():void
		{	
			addChild(_slice);
			addChild(_hitZone = new Sprite());
			
			hitArea = _hitZone;
			mouseChildren = false;
			buttonMode = mouseEnabled = _hitZone.mouseEnabled = true;
			
			_draw(_hitZone.graphics);
			
			addEventListener(Event.REMOVED_FROM_STAGE, _onRemoved);
			_hitZone.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
		}
		
		/** @private */
		private function _draw(pGraphics:Graphics):void
		{
			var g:Graphics = pGraphics;
			
			g.clear();
			g.beginFill(0, 0);
			g.drawRect(_rect.x, _rect.y, _rect.width, _rect.height);
			g.endFill();
		}
		
		/** @private */
		private function _checkLimit(pValue:Number) : Number
		{
			var lenght : int = _slice.totalFrames;
			while ( pValue > lenght ) pValue -= lenght;
			while ( pValue < 0 ) pValue += lenght;
			
			return pValue;
		}
		
		/** @private */
		private function _getXFrame() : Number
		{
			return (_hitZone.mouseX - _hitZone.x) / ( _hitZone.width / _coeff ) * _slice.totalFrames;
		}
		
		
		
		/* CONTENT */
		private var _slice:ClAbstractSlicePlayer;
		private var _hitZone : Sprite;
		
		/* VAR */
		private var _f : Number = 1;
		private var _lastFrame : Number = 0;
		private var _xFrame : Number = 0;
		private var _indice : Number = 0;
		private var _isDragging : Boolean;
		private var _coeff:Number = .2;
		private var _rect:Rectangle;
		
		/* CONST */
		private const _VELOCITY:Number = .2;
	}
}
